package com.lll.simple.rpc.protocol.serialization;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.BeanSerializer;
import com.lll.simple.rpc.common.RpcRequest;
import com.lll.simple.rpc.common.RpcResponse;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @Author: liull
 * @Description: kryo serialization TODO:这个有问题
 * @Date: Created in 15:07 2021/2/7
 * @Modified By:
 */
public class KryoSerialization implements RpcSerialization {
    private static final ThreadLocal<Kryo> KRYO_LOCAL = ThreadLocal.withInitial(() -> {
        Kryo kryo = new Kryo();
        kryo.setReferences(false);
        kryo.setRegistrationRequired(false);
        kryo.addDefaultSerializer(RpcRequest.class, BeanSerializer.class);
        kryo.addDefaultSerializer(RpcResponse.class, BeanSerializer.class);
        return kryo;
    });

    @Override
    public <T> byte[] serialize(T obj) throws IOException {
        try {
            Kryo kryo = KRYO_LOCAL.get();
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            Output output = new Output(byteArrayOutputStream);
            kryo.writeClassAndObject(output, obj);
            output.close();
            return byteArrayOutputStream.toByteArray();
        } catch (Throwable t) {
            return null;
        } finally {
            // 防止内存泄露
            KRYO_LOCAL.remove();
        }
    }

    @Override
    public <T> T deserialize(byte[] data, Class<T> clazz) throws IOException {
        try {
            Kryo kryo = KRYO_LOCAL.get();
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
            Input input = new Input(byteArrayInputStream);
            input.close();
            return (T) kryo.readObjectOrNull(input, clazz);
        } catch (Throwable t) {
            return null;
        } finally {
            // 防止内存泄露
            KRYO_LOCAL.remove();
        }
    }

}
